<?php


namespace App\Tools;


use App\Models\MerchantShop;
use App\Models\MerchantUser;
use App\Models\NoTbPlatform;
use App\Models\OrderRecord;
use App\Models\PushLevel;
use App\Models\PushTask;
use App\Models\PushTbPlatform;
use App\Models\PushUser;
use App\Models\SaleAssess;
use App\Models\SaleTask;
use App\Models\ShopGroup;
use App\Models\SystemConfig;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class FindUsers
{
    private $tasks;
    private $totalUserCount;
    private $isZqd;
    private $isForceDispatch;

    public function __construct($task, $totalUserCount)
    {
        $this->tasks = $task;
        // 状态为正常的刷手总数量
        $this->totalUserCount = $totalUserCount;
        // 是否销量单
        // 是否增权单
        $this->isZqd = $this->tasks['zqd'];
        // 是否强制派单
        $this->isForceDispatch = $this->isForceDispatch();
    }

    /*
     * 普通单派单
     */
    public function run()
    {
        $findUserNum = 0;
        $blackNum = 0;//拉黑次数
        $goodRepeatNum = 0;
        $shopRepeatNum = 0;
        $posRepeatNum = 0;
        $shopGroupRepeatNum = 0;
        $platformLimitNum = 0;
        $tagLimitNum = 0;
        $levelLimitNum = 0;
        $zqdLimitNum = 0;

        $planInfo = $this->tasks['plan_info'];

        // 获取状态为 1：正常 的刷手
        $pushUser = PushUser::where('status', 1);
        // 根据金额筛选等级
        $shouldPay = bcmul($this->tasks['pay_money'], $this->tasks['buy_num']);
        $pushLevelList = PushLevel::get();
        $levels = [];
        if (!empty($pushLevelList)) {
            foreach ($pushLevelList as $value) {
                if (bccomp($shouldPay, $value->min_money) >= 0 && bccomp($shouldPay, $value->max_money) <= 0) {
                    $levels[] = $value->id;
                }
            }
        }
        $pushUser->whereIn('level', $levels);
        // 标签限制
        if (SystemConfig::findValue('dispatch.taglimit') == 1) {
            // 性别
            if (isset($planInfo['sex_id']) && $planInfo['sex_id'] != '' && $planInfo['sex_id'] != '99' && $planInfo['sex_id'] != 0) {
                $pushUser->where('sex', $planInfo['sex_id']);
            }
            // 信用
            if (isset($planInfo['credit_id']) && $planInfo['credit_id'] != '' && $planInfo['credit_id'] != '99' && $planInfo['credit_id'] != 0) {
                $pushUser->where('credit', $planInfo['credit_id']);
            }
            // 系统
            if (isset($planInfo['model_id']) && $planInfo['model_id'] != '' && $planInfo['model_id'] != '99' && $planInfo['model_id'] != 0) {
                $pushUser->where('system', $planInfo['model_id']);
            }
            //地区
            if (isset($planInfo['placement_area']) && !empty(trim($planInfo['placement_area'], ' '))) {
                $type = substr($planInfo['placement_area'], 0, 1);
                $placeStr = substr($planInfo['placement_area'], 1);
                $placeArray = explode(',', $placeStr);
                if (!empty($placeArray)) {
                    // 选中地区
                    if ($type == '+') {
                        $pushUser->whereIn('province', $placeArray);
                    }elseif ($type == '-') {
                        $pushUser->whereNotIn('province', $placeArray);
                    }
                }
            }
            // 年龄
            if (isset($planInfo['age_id']) && $planInfo['age_id'] != '' && $planInfo['age_id'] != '99' && $planInfo['age_id'] != 0) {
                $isAgeLimit = SystemConfig::findValue('dispatch.agelimit', 1) == 1;
                $ageArray = explode(',', $planInfo['age_id']);
                if ($isAgeLimit && !empty($ageArray)) {
                    $pushUser->whereIn('age', $ageArray);
                }
            }
        }

        // 复购查询
        $findRepeats = new FindRepeats($this->tasks);
        $repeatSql = $findRepeats->getNotExists();
//        $repeatResult = $findRepeats->getList();
        // 最大接单人数
        $maxGetOrderNum = SystemConfig::findValue('dispatch.maxGetOrderNum2', 64);

        $userArray = [];
        $sortUserArray = [];
        $count = 0;

        $isTb = in_array($this->tasks['platform_type'], [1, 2, 4]);
        $isOtherPlatform = in_array($this->tasks['platform_type'], [3, 13, 15]);

        if ($this->isForceDispatch) {
            // 强制派单要判断身份证是否审核通过
            $pushUser->where('id_card_status', 1);
            if (!empty($repeatSql)) {
                $pushUser->whereRaw("id not in (select DISTINCT push_id from ({$repeatSql}) a)");
                Logs::info("本次复购sql", [$repeatSql], 'dispatch', $this->tasks['task_code']);
            }
            else{
                Logs::info("本次无复购数据", [], 'dispatch', $this->tasks['task_code']);
            }

//            $pushUser->limit($maxGetOrderNum * 5);
            $pushUserList = $pushUser->orderBy(DB::raw('RAND()'))->limit(150)->get();
        }else{
            // 状态为已开启接单
            $pushUser->where('orders_status', 1);
            if (!empty($repeatSql)) {
                $pushUser->whereRaw("id not in (select DISTINCT push_id from ({$repeatSql}) a)");
                Logs::info("本次复购sql", [$repeatSql], 'dispatch', $this->tasks['task_code']);
            }
            else{
                Logs::info("本次无复购数据", [], 'dispatch', $this->tasks['task_code']);
            }
            $pushUserList = $pushUser->orderBy(DB::raw('RAND()'))->limit(150)->get();//rand()
        }

        if (empty($pushUserList)) {
            Logs::info("无法筛选到匹配刷手", [$repeatSql], 'dispatch', $this->tasks['task_code']);
            Log::info("无法筛选到匹配刷手: {$this->tasks['task_code']}");
            // 释放订单共享锁 删除日志目录
            $dispatch_task_id = json_decode(Redis::get("dispatch_task_code"), true);
            $dispatch_taskid_key = array_search($this->tasks['id'], $dispatch_task_id);
            array_splice($dispatch_task_id, $dispatch_taskid_key, 1);
            Redis::set("dispatch_task_code", json_encode($dispatch_task_id));
            $orderLockFileName = storage_path("logs/{$this->tasks['task_code']}/");
            File::deleteDirectory($orderLockFileName);
            return false;
        }
        Logs::info("排除复购后匹配到人数", [$pushUserList->count()], 'dispatch', $this->tasks['task_code']);

        // 截取一百个用户进行匹配
//        if ($pushUserList->count() > 100) {
//            $pushUserList = array_slice($pushUserList->toArray(), 0, 100);
//        }
        if ($isTb) {
            // 初始化排序的数组， // 按照5 4 3 2 1排序
            for ($i = 5; $i > 0; $i--) {
                $sortUserArray[$i] = [];
            }
        }

        $skipCount = 0;
        foreach ($pushUserList as $value) {
            // 强制开启接单的时候要判断用户是否有正在操作的任务
            if ($this->isForceDispatch) {
                $pushTaskList = PushTask::where('push_id', $value['id'])->whereIn('status', [1, 4])->exists();
                if ($pushTaskList) {
                    $skipCount++;
                    continue;
                }
                $saleAssessInfo = SaleAssess::where('push_id', $value['id'])->whereIn('status', [1, 2])->exists();
                if ($saleAssessInfo) {
                    $skipCount++;
                    continue;
                }
            }

            // 判断是否有对应平台的账号
            if ($isTb) {
                $pushPlatformInfo = PushTbPlatform::where('push_id', $value['id'])->where('status', 4)->first();
                if (empty($pushPlatformInfo) || !isset($pushPlatformInfo->platform_name)) {
                    continue;
                }
                $value['platform_name'] = $pushPlatformInfo->platform_name;
                if (!$this->tasks['zqd']) {
                    $pushUserPlanNumInfo = $this->isTaskNumLimit($value['id']);
                    if ($pushUserPlanNumInfo) {
                        continue;
                    }
                    if ($this->isIpRepeat($value)) {
                        continue;
                    }
                }

                // 存入排序数组
                $sortUserArray[$pushPlatformInfo->tb_status][] = $value;
                $count++;
                // 淘宝平台走不同逻辑，所以直接跳出
                continue;
            }elseif ($isOtherPlatform) {
                $pushPlatformInfo = NoTbPlatform::where('push_id', $value['id'])
                    ->where('platform_type', $this->tasks['platform_type'])
                    ->where('status', 1)->first();
                if (empty($pushPlatformInfo)) {
                    continue;
                }
                $value['platform_name'] = $pushPlatformInfo->platform_name;
            }else{
                continue;
            }

            if (!$this->isZqd) {
                // 判断是否已经超过做单限制
                $pushUserPlanNumInfo = $this->isTaskNumLimit($value['id']);
                if ($pushUserPlanNumInfo) {
                    continue;
                }

                // 排除ip重复的用户
                if ($this->isIpRepeat($value)) {
                    continue;
                }
            }

            $userArray[] = $value;
            $count++;
        }

        // 将排序的数据合并
        if ($isTb) {
            foreach ($sortUserArray as $value) {
                foreach ($value as $val) {
                    array_push($userArray, $val);
                }
            }
        }

        if (empty($userArray)) {
            Logs::info("无法匹配到接单刷手", [], 'dispatch', $this->tasks['task_code']);
            Log::info("无法匹配到接单刷手: {$this->tasks['task_code']}");
            // 释放订单共享锁 删除日志目录
            $dispatch_task_id = json_decode(Redis::get("dispatch_task_code"), true);
            $dispatch_taskid_key = array_search($this->tasks['id'], $dispatch_task_id);
            array_splice($dispatch_task_id, $dispatch_taskid_key, 1);
            Redis::set("dispatch_task_code", json_encode($dispatch_task_id));
            $orderLockFileName = storage_path("logs/{$this->tasks['task_code']}/");
            File::deleteDirectory($orderLockFileName);
            return false;
        }

        // 打乱数组顺序, 降低匹配重复率
        $users = array_merge($userArray);
        $users = shuffle_assoc($users);

        $totalGetOrderUserNum = count($users);
        Logs::info("本次最终派单人数", [$totalGetOrderUserNum], 'dispatch', $this->tasks['task_code']);

        foreach ($users as $uv) {
            $findUserNum++;

            $uid = $uv['id'];
            // 等级不够跳过
            if (!isset($uv['level']) || $uv['level'] == '') {
                Logs::info("等级不够跳过", [$uid], 'dispatch', $this->tasks['task_code']);
                continue;
            }
            // 平台账号判断


            $level = PushLevel::where('id', $uv['level'])->exists();
            // 买手等级没有设置
            if (!$level) {
                Logs::info("买手等级没有设置", [$uid], 'dispatch', $this->tasks['task_code']);
                continue;
            }

            $salePlanInfo = $planInfo;

            try {
                if (Redis::exists("dispatch_uid")) {
                    $dispatch_uid = json_decode(Redis::get("dispatch_uid"), true);
                    if (in_array($uid, $dispatch_uid)) {
                        Logs::info("被派单中，跳过", [$uid], 'dispatch', $this->tasks['task_code']);
                        continue;
                    }
                }
                // 先判断刷手当前是否有任务, 且状态不为1 ，4
                $is_push_task = PushTask::where('push_id', $uid)->whereIn('status', [1, 4])->first();
                if (!empty($is_push_task)) {
                    Logs::info("已有任务，跳过", [$uid], 'dispatch', $this->tasks['task_code']);
                    continue;
                }
                // 确认任务是否派出
                $is_task = PushTask::whereIn('status', [1, 4, 6, 7, 9, 10])
                    ->where('task_type', 1)->where('task_id', $this->tasks['id'])->first();
                if (!empty($is_task)) {
                    Logs::info("task已在派单中，跳过", [$this->tasks['task_code']], 'dispatch', $this->tasks['task_code']);
                    // 释放订单共享锁 删除日志目录
                    $dispatch_task_id = json_decode(Redis::get("dispatch_task_code"), true);
                    $dispatch_taskid_key = array_search($this->tasks['id'], $dispatch_task_id);
                    array_splice($dispatch_task_id, $dispatch_taskid_key, 1);
                    Redis::set("dispatch_task_code", json_encode($dispatch_task_id));
                    $orderLockFileName = storage_path("logs/{$this->tasks['task_code']}/");
                    File::deleteDirectory($orderLockFileName);
                    break;
                }

                // 将开始用户缓存到redis共享缓存
                $dispatch_uid[] = $uid;
                Redis::set("dispatch_uid", json_encode($dispatch_uid));

                $saleTask = SaleTask::where('id', $this->tasks['id'])->first();
                if (empty($saleTask) || $saleTask->status != 1) {
                    // 释放订单共享锁 删除日志目录
                    $dispatch_task_id = json_decode(Redis::get("dispatch_task_code"), true);
                    $dispatch_taskid_key = array_search($this->tasks['id'], $dispatch_task_id);
                    array_splice($dispatch_task_id, $dispatch_taskid_key, 1);
                    Redis::set("dispatch_task_code", json_encode($dispatch_task_id));
                    $orderLockFileName = storage_path("logs/{$this->tasks['task_code']}/");
                    File::deleteDirectory($orderLockFileName);
                    return;
                }

                $createResult = DB::transaction(function () use ($salePlanInfo, $uid, $uv) {
                    $pushTask = PushTask::create([
                        'merchant_id' => $salePlanInfo['merchant_id'],
                        'plan_id' => $this->tasks['plan_id'],
                        'task_id' => $this->tasks['id'],
                        'plan_code' => $this->tasks['plan_code'],
                        'task_code' => $this->tasks['task_code'],
                        'shop_type' => $this->tasks['platform_type'],
                        'push_id' => $uid,
                        'shop_id' => $salePlanInfo['shop_id'],
                        'goods_id' => $salePlanInfo['goods_id'],
                        'keyword' => $this->tasks['keyword'],
                        'commission' => $this->tasks['push_commission'],
                        'tb_name' => $uv['platform_name'],
                        'pay_money' => $this->tasks['pay_money'],
                        'create_time' => time(),
                        'status' => 1,
                        'task_type' => 1,
                        'buy_num' => $this->tasks['buy_num'],
                        'rebate_type' => $salePlanInfo['rebate_type'],
                        'dispatch_in' => 2
                    ]);
                    if (!empty($pushTask)) {
                        Logs::info("用户派单成功,事物打印1", [$uid, $this->tasks['task_code']], 'dispatch', $this->tasks['task_code']);
                    }
                    // pushTask 创建成功
                    SaleTask::where('id', $this->tasks['id'])->update([
                        'status' => 2
                    ]);
                    if (!empty($pushTask)) {
                        Logs::info("用户派单成功,事物打印2", [$uid, $this->tasks['task_code']], 'dispatch', $this->tasks['task_code']);
                    }

                    return $pushTask;
                });

                if (!empty($createResult)) {
                    PushUser::where('id', $uid)->update([
                        'orders_status' => 2
                    ]);
                    Logs::info("派单成功,发送通知", [$uid, $this->tasks['task_code']], 'dispatch', $this->tasks['task_code']);
                    Log::info("派单成功：{$this->tasks['task_code']}");
                    // 发送微信通知
                    $url = getenv('API_URL')."/wechart/sendWechatNotice?pushId={$uid}&orderNum={$this->tasks['task_code']}";
                    curl_request($url);
                    // 释放用户共享锁
                    $dispatch_uid = json_decode(Redis::get("dispatch_uid"), true);
                    $dispatch_uid_key = array_search($uid, $dispatch_uid);
                    array_splice($dispatch_uid, $dispatch_uid_key, 1);
                    Redis::set("dispatch_uid", json_encode($dispatch_uid));
                    // 释放订单共享锁 删除日志目录
                    $dispatch_task_id = json_decode(Redis::get("dispatch_task_code"), true);
                    $dispatch_taskid_key = array_search($this->tasks['id'], $dispatch_task_id);
                    array_splice($dispatch_task_id, $dispatch_taskid_key, 1);
                    Redis::set("dispatch_task_code", json_encode($dispatch_task_id));
                    $orderLockFileName = storage_path("logs/{$this->tasks['task_code']}/");
                    File::deleteDirectory($orderLockFileName);
                    break;
                }
                // 没有被break出去，代表派单失败
                Log::info("派单失败：{$this->tasks['task_code']}");
                Logs::info("派单失败", [$uid, $this->tasks['task_code']], 'dispatch', $this->tasks['task_code']);
                // 释放用户共享锁
                $dispatch_uid = json_decode(Redis::get("dispatch_uid"), true);
                $dispatch_uid_key = array_search($uid, $dispatch_uid);
                array_splice($dispatch_uid, $dispatch_uid_key, 1);
                Redis::set("dispatch_uid", json_encode($dispatch_uid));
                // 释放订单共享锁 删除日志目录
                $dispatch_task_id = json_decode(Redis::get("dispatch_task_code"), true);
                $dispatch_taskid_key = array_search($this->tasks['id'], $dispatch_task_id);
                array_splice($dispatch_task_id, $dispatch_taskid_key, 1);
                Redis::set("dispatch_task_code", json_encode($dispatch_task_id));
                $orderLockFileName = storage_path("logs/{$this->tasks['task_code']}/");
                File::deleteDirectory($orderLockFileName);
            }catch (QueryException $exception) {
                Logs::info("错误信息", [$exception->getMessage()], 'dispatch', $this->tasks['task_code']);
                Logs::info("派单失败", [$uid, $this->tasks['task_code']], 'dispatch', $this->tasks['task_code']);
                Log::info("派单失败：{$this->tasks['task_code']}");
                // 释放用户共享锁
                $dispatch_uid = json_decode(Redis::get("dispatch_uid"), true);
                $dispatch_uid_key = array_search($uid, $dispatch_uid);
                array_splice($dispatch_uid, $dispatch_uid_key, 1);
                Redis::set("dispatch_uid", json_encode($dispatch_uid));
                // 释放订单共享锁 删除日志目录
                $dispatch_task_id = json_decode(Redis::get("dispatch_task_code"), true);
                $dispatch_taskid_key = array_search($this->tasks['id'], $dispatch_task_id);
                array_splice($dispatch_task_id, $dispatch_taskid_key, 1);
                Redis::set("dispatch_task_code", json_encode($dispatch_task_id));
                $orderLockFileName = storage_path("logs/{$this->tasks['task_code']}/");
                File::deleteDirectory($orderLockFileName);
            }
        }

        // 释放订单共享锁 删除日志目录
        $dispatch_task_id = json_decode(Redis::get("dispatch_task_code"), true);
        $dispatch_taskid_key = array_search($this->tasks['id'], $dispatch_task_id);
        array_splice($dispatch_task_id, $dispatch_taskid_key, 1);
        Redis::set("dispatch_task_code", json_encode($dispatch_task_id));
        $orderLockFileName = storage_path("logs/{$this->tasks['task_code']}/");
        File::deleteDirectory($orderLockFileName);

        OrderRecord::create([
            'task_id' => $this->tasks['id'],
            'plan_type' => $this->tasks['plan_type'],
            'create_time' => time(),
            'remark' => $this->totalUserCount."/".$totalGetOrderUserNum."/".$findUserNum."/".$blackNum."/".$goodRepeatNum."/".$shopRepeatNum."/".$posRepeatNum."/".$shopGroupRepeatNum."/".$platformLimitNum."/".$tagLimitNum."/".$levelLimitNum."/".$zqdLimitNum
        ]);

    }

    public function runZqd()
    {
        $maxGetOrderNum = SystemConfig::findValue('dispatch.maxGetOrderNum2', 64);
        $platformType = $this->tasks['platform_type'];

        $planInfo = $this->tasks['plan_info'];
        $shopId = $planInfo['shop_id'];
        $goodsId = $planInfo['goods_id'];
        $merchantId = $planInfo['merchant_id'];
        $pushTaskList = PushTask::where('status', 7)
            ->where('check_status', 2)
            ->where('task_type', 2)
            ->where('shop_id', $shopId)
            ->where('goods_id', $goodsId)
            ->where('merchant_id', $merchantId)
            ->get();
        if (!empty($pushTaskList)) {
            return;
        }
        $pushUserIds = [];

        foreach ($pushTaskList as $pushTaskInfo) {
            if (!isset($pushTaskInfo->over_time) || $this->isZqdTimeLimit($pushTaskList->over_time, $planInfo['zqd_type'] ?? 0)) {
                continue;
            }
            $pushUserIds[] = $pushTaskInfo->push_id;
        }

        $isTb = in_array($this->tasks['platform_type'], [1, 2, 4]);
        $isOtherPlatform = in_array($this->tasks['platform_type'], [3, 13, 15]);

        $pushUser = PushUser::where('status', 1);
        if (!$this->isForceDispatch) {
            $pushUser->where('orders_status', 1);
        }
        $pushUser->whereIn('id', $pushUserIds);

        if ($this->isForceDispatch &&  !$this->isZqd) {
            $pushUser->limit($maxGetOrderNum * 5);
            $pushUserList = $pushUser->get();
        }else{
            if ($this->tasks['zqd']) {
                $pushUser->orderBy('sale_complete_num', 'asc');
            }
            $pushUser->limit($maxGetOrderNum/2);
            $pushUserList = $pushUser->get();
        }

        if ($isTb) {
            // 初始化排序的数组， // 按照5 4 3 2 1排序
            for ($i = 5; $i > 0; $i--) {
                $sortUserArray[$i] = [];
            }
        }

        $skipCount = 0;
        foreach ($pushUserList as $value) {
            // 强制开启接单的时候要判断用户是否有正在操作的任务
            if ($this->isForceDispatch) {
                $pushTaskList = PushTask::where('push_id', $value->id)->whereIn('status', [1, 4])->get();
                if (!empty($pushTaskList)) {
                    $skipCount++;
                    continue;
                }
                $saleAssessInfo = SaleAssess::where('push_id', $value->id)->whereIn('status', [1, 2])->get();
                if (!empty($saleAssessInfo)) {
                    $skipCount++;
                    continue;
                }
            }

            // 判断是否有对应平台的账号
            if ($isTb) {
                $pushPlatformInfo = PushTbPlatform::where('push_id', $value->id)->where('status', 4)->first();
                if (empty($pushPlatformInfo) || !isset($pushPlatformInfo->platform_name)) {
                    continue;
                }
                $value->platform_name = $pushPlatformInfo->platform_name;
                if (!$this->tasks['zqd']) {
                    $pushUserPlanNumInfo = $this->isTaskNumLimit($value->id);
                    if ($pushUserPlanNumInfo) {
                        continue;
                    }

                    if ($this->isIpRepeat($value)) {
                        continue;
                    }
                }

                // 存入排序数组
                $sortUserArray[$pushPlatformInfo->tb_status][] = $value->toArray();
                $count++;
                // 淘宝平台走不同逻辑，所以直接跳出
                continue;
            }elseif ($isOtherPlatform) {
                $pushPlatformInfo = NoTbPlatform::where('push_id', $value->id)
                    ->where('platform_type', $this->tasks['platform_type'])
                    ->where('status', 1)->first();
                if (empty($pushPlatformInfo)) {
                    continue;
                }
                $value->platform_name = $pushPlatformInfo->platform_name;
            }else{
                continue;
            }

            if (!$this->tasks['zqd']) {
                // 判断是否已经超过做单限制
                $pushUserPlanNumInfo = $this->isTaskNumLimit($value->id);
                if ($pushUserPlanNumInfo) {
                    continue;
                }

                // 排除ip重复的用户
                if ($this->isIpRepeat($value)) {
                    continue;
                }
            }

            $userArray[] = $value->toArray();
            $count++;
        }

        // 将排序的数据合并
        if ($isTb) {
            foreach ($sortUserArray as $value) {
                foreach ($value as $val) {
                    array_push($userArray, $val);
                }
            }
        }

        // 打乱数组顺序
        $pushUserList = array_merge($userArray);
        $pushUserList = shuffle_assoc($pushUserList);

        $orderUserNum = count($pushUserList);// 开启接单人数
        $findUserNum = 0;
        $blackNum = 0; // 拉黑次数
        $goodsRepeatNum = 0;
        $shopRepeatNum = 0;
        $posRepeatNum = 0;
        $shopGroupRepeatNum = 0;
        $platformLimitNum = 0;
        $tagLimitNum = 0;
        $levelLimitNum = 0;
        $zqdLimitNum = 0;
        $pushUserCode = null;

        // 先把黑名单查出来
        $shopType = $platformType;

        foreach ($pushUserList as $pushUserInfo) {
            // 派单超过最大派单次数跳过派单
            if ($findUserNum >= $maxGetOrderNum) {
                break;
            }
            $findUserNum++;
            $uid = $pushUserInfo['id'];
            // 等级不够跳过
            if (!isset($pushUserInfo['level']) || $pushUserInfo['level'] == '') {
                continue;
            }

            $level = PushLevel::where('id', $pushUserInfo['level'])->first();
            // 买手等级没有设置
            if (empty($level)) {
                continue;
            }
            // 销量任务
            $salePlanInfo = $planInfo;
            $shouldPay = bcmul($this->tasks['pay_money'], $this->tasks['buy_num']);
            if (bccomp($shouldPay, $level['min_money']) > 0 || bccomp($shouldPay, $level->max_money) > 0) {
                $levelLimitNum ++;
                continue;
            }
            // 按照商户组-》商户-》店铺-》商品查询，可以减少查询次数
            $isZqdShopGroupRepeatLimit = SystemConfig::findValue('dispatch.zqdshopgrouprepeatlimit') == 1;
            if ($isZqdShopGroupRepeatLimit) {
                $shopGroupRepeat = $this->isRepeat('posgroup', $salePlanInfo['shop_id'], $pushUserInfo, $this->tasks);
                if ($shopGroupRepeat) {
                    $shopGroupRepeatNum++;
                    continue;
                }
            }
            $posRepeat = $this->isRepeat('pos', $salePlanInfo['merchant_id'], $pushUserInfo, $this->tasks);
            if ($posRepeat) {
                $posRepeatNum++;
                continue;
            }
            $shopRepeat = $this->isRepeat('shop', $salePlanInfo['shop_id'], $pushUserInfo, $this->tasks);
            if ($shopRepeat) {
                $shopRepeatNum++;
                continue;
            }
            // 同商品不能重复接
            $goodRepeat = $this->isRepeat('good', $salePlanInfo['goods_id'], $pushUserInfo, $this->tasks);
            if ($goodRepeat) {
                $goodsRepeatNum++;
                continue;
            }
            // 排除ip重复的用户
            if ($this->isIpRepeat($pushUserInfo)) {
                continue;
            }


            try {
                if (Redis::exists("dispatch_uid")) {
                    $dispatch_uid = json_decode(Redis::get("dispatch_uid"), true);
                    if (in_array($uid, $dispatch_uid)) {
                        Logs::info("【{$uid}】被派单中,跳过 ", [], 'dispatch', $this->tasks['task_code']);
                        continue;
                    }
                }
                $is_push_task = PushTask::where('push_id', $uid)->whereIn('status', [1, 4])->first();
                if (!empty($is_push_task)) {
                    Logs::info("【{$uid}】已经有任务，跳过 ", [], 'dispatch', $this->tasks['task_code']);
                    continue;
                }

                // 确认任务是否派出
                $is_task = PushTask::whereIn('status', [1, 4, 6, 7, 9, 10])
                    ->where('task_type', 1)->where('task_id', $this->tasks['id'])->first();
                if (!empty($is_task)) {
                    // 释放订单共享锁 删除日志目录
                    $dispatch_task_id = json_decode(Redis::get("dispatch_task_code"), true);
                    $dispatch_taskid_key = array_search($this->tasks['id'], $dispatch_task_id);
                    array_splice($dispatch_task_id, $dispatch_taskid_key, 1);
                    Redis::set("dispatch_task_code", json_encode($dispatch_task_id));
                    $orderLockFileName = storage_path("logs/{$this->tasks['task_code']}/");
                    File::deleteDirectory($orderLockFileName);
                    break;
                }

                $dispatch_uid[] = $uid;
                Redis::set("dispatch_uid", json_encode($dispatch_uid));
                Logs::info("开始给 【{$uid}】派单 ", [], 'dispatch', $this->tasks['task_code']);

                $createResult = DB::transaction(function () use ($salePlanInfo, $shopType, $uid, $pushUserInfo) {
                    $pushTask = PushTask::create([
                        'merchant_id' => $salePlanInfo['merchant_id'],
                        'plan_id' => $this->tasks['plan_id'],
                        'task_id' => $this->tasks['id'],
                        'plan_code' => $this->tasks['plan_code'],
                        'task_code' => $this->tasks['task_code'],
                        'shop_type' => $shopType,
                        'push_id' => $uid,
                        'shop_id' => $salePlanInfo['shop_id'],
                        'goods_id' => $salePlanInfo['goods_id'],
                        'keyword' => $this->tasks['keyword'],
                        'commission' => $this->tasks['push_commission'],
                        'tb_name' => $pushUserInfo['platform_name'],
                        'pay_money' => $this->tasks['pay_money'],
                        'create_time' => time(),
                        'status' => 1,
                        'task_type' => 1,
                        'buy_num' => $this->tasks['buy_num'],
                        'rebate_type' => $salePlanInfo['rebate_type'],
                        'dispatch_in' => 2
                    ]);
                    SaleTask::where('id', $this->tasks['id'])->where('status', $this->tasks['status'])->update([
                        'status' => 2
                    ]);

                    if (!empty($pushTask)) {
                        Logs::info("【{$uid}】-[{$this->tasks['id']}]派单成功 ,事物打印1", [], 'dispatch', $this->tasks['task_code']);
                    }
                    // pushTask 创建成功
                    SaleTask::where('id', $this->tasks['id'])->update([
                        'status' => 2
                    ]);
                    if (!empty($pushTask)) {
                        Logs::info("【{$uid}】-[{$this->tasks['id']}]派单成功 ,事物打印2", [], 'dispatch', $this->tasks['task_code']);
                    }

                    return $pushTask;

                });

                // 释放用户共享锁
                $dispatch_uid = json_decode(Redis::get("dispatch_uid"), true);
                $dispatch_uid_key = array_search($uid, $dispatch_uid);
                array_splice($dispatch_uid, $dispatch_uid_key, 1);
                Redis::set("dispatch_uid", json_encode($dispatch_uid));
                // 释放订单共享锁 删除日志目录
                $dispatch_task_id = json_decode(Redis::get("dispatch_task_code"), true);
                $dispatch_taskid_key = array_search($this->tasks['id'], $dispatch_task_id);
                array_splice($dispatch_task_id, $dispatch_taskid_key, 1);
                Redis::set("dispatch_task_code", json_encode($dispatch_task_id));
                $orderLockFileName = storage_path("logs/{$this->tasks['task_code']}/");
                File::deleteDirectory($orderLockFileName);

                if (!empty($createResult)) {
                    PushUser::where('id', $uid)->update([
                        'orders_status' => 2
                    ]);
                    // 发送微信通知
                    $url = getenv('API_URL')."/wechart/sendWechatNotice?pushId={$uid}&orderNum={$this->tasks['task_code']}";
                    curl_request($url);
                    Logs::info("【{$uid}】派单成功", [], 'dispatch', $this->tasks['task_code']);
                    break;
                }
                // 没有被break出去，代表派单失败
                Logs::info("【{$uid}】派单失败", [], 'dispatch', $this->tasks['task_code']);
            }catch (QueryException $exception) {
                Log::info($exception->getMessage());
                Logs::info("【{$uid}】派单失败", [], 'dispatch', $this->tasks['task_code']);
                // 释放用户共享锁
                $dispatch_uid = json_decode(Redis::get("dispatch_uid"), true);
                $dispatch_uid_key = array_search($uid, $dispatch_uid);
                array_splice($dispatch_uid, $dispatch_uid_key, 1);
                Redis::set("dispatch_uid", json_encode($dispatch_uid));
                // 释放订单共享锁 删除日志目录
                $dispatch_task_id = json_decode(Redis::get("dispatch_task_code"), true);
                $dispatch_taskid_key = array_search($this->tasks['id'], $dispatch_task_id);
                array_splice($dispatch_task_id, $dispatch_taskid_key, 1);
                Redis::set("dispatch_task_code", json_encode($dispatch_task_id));
                $orderLockFileName = storage_path("logs/{$this->tasks['task_code']}/");
                File::deleteDirectory($orderLockFileName);
            }
        }
        OrderRecord::create([
            'task_id' => $this->tasks['id'],
            'plan_type' => $this->tasks['plan_type'],
            'create_time' => time(),
            'remark' => $this->totalUserCount."/".$orderUserNum."/".$findUserNum."/".$blackNum."/".$goodsRepeatNum."/".$shopRepeatNum."/".$posRepeatNum."/".$shopGroupRepeatNum."/".$platformLimitNum."/".$tagLimitNum."/".$levelLimitNum."/".$zqdLimitNum
        ]);

    }

    /**
     * 判断店铺组、商户、店铺、商品限制
     * @param $type
     * @param $id
     * @param $pushUserInfo
     * @param $task
     * @param null $planType
     * @return bool
     */
    private function isRepeat($type, $id, $pushUserInfo, $task)
    {

        $platformType = $task['platform_type'];

        $pushTask = PushTask::where('push_id', $pushUserInfo['id']);

        $isTbOrJd = $platformType == 1 || $platformType == 2 || $platformType == 3 || $platformType == 4;
        $pushTask->where('task_type', 1);
        if ($type == 'good') {

            //是否要派给领取后放弃用户
            if(SystemConfig::findValue('dispatch.togiveupuser',1) == 1){
                $pushTask->whereIn('status', [6, 7, 8]);
            } else {
                $pushTask->whereIn('status', [3, 6, 7, 8]);
            }
            //没有开启限制
            if (SystemConfig::findValue('dispatch.goodrepeatlimit') != 1) {
                return false;
            }
            $key = $isTbOrJd?'posputplan.good1':'posputplan.good2';
            $pushTask->where('goods_id', $id);

        } elseif ($type == 'shop') {
            $pushTask->whereIn('status', [6, 7, 8]);
            //没有开启限制
            if (SystemConfig::findValue('dispatch.shoprepeatlimit') != 1) {
                return false;
            }
            $key = $isTbOrJd?'posputplan.shop1':'posputplan.shop2';
            $pushTask->where('shop_id', $id);
        } elseif ($type == 'pos') {
            $pushTask->whereIn('status', [6, 7]);
            //没有开启限制
            if (SystemConfig::findValue('dispatch.posrepeatlimit') != 1) {
                return false;
            }
            $key = $isTbOrJd?'posputplan.pos1':'posputplan.pos2';

            $tb = [1, 2, 4];
            if(in_array($platformType, $tb)){
                $pushTask->whereIn('shop_type', $tb);
            }else{
                $pushTask->where('shop_type', $platformType);
            }
            $pushTask->where('merchant_id', $id);
        } elseif ($type == 'posgroup') { //店铺组
            $pushTask->whereIn('status', [6, 7]);
            //没有开启限制
            if (SystemConfig::findValue('dispatch.posgrouprepeatlimit') != 1) {
                return false;
            }

            $merchantShopInfo = MerchantShop::where('id', $id)->first();
            if (!isset($merchantShopInfo->group_id) || $merchantShopInfo->group_id == '') {
                return false;
            }
            $merchantShopGroup = MerchantShop::where('group_id', $merchantShopInfo->group_id)->get();
            if (!$merchantShopGroup) {
                return false;
            }

            $retGp = [];
            foreach ($merchantShopGroup as $k => $v) {
                $retGp[$k] = $v->id;
            }
            $pushTask->whereIn('shop_id', $retGp);

            $day = ShopGroup::where('id', $merchantShopInfo->group_id)->value('days');
            $st = (time() - ($day * 24 * 60 * 60));
            $et = time();
            $pushTask->whereBetween('create_time', [$st, $et]);
            $pushTaskInfo = $pushTask->first();
            if (!empty($pushTaskInfo)) {
                return true;
            }
            return false;
        } else {
            return false;
        }
        $value = SystemConfig::findValue($key);
        if (!$value) {
            return false;
        }
        $st = (time() - ($value * 24 * 60 * 60));
        $et = time();
        $pushTask->whereBetween('create_time', [$st, $et]);
        $pushTaskInfo = $pushTask->first();
        if (!empty($pushTaskInfo)) {
            return true;
        }
        return false;

    }

    private function isZqdTimeLimit($taskTime, $zqdType){
        $zero = strtotime(date('Ymd'));
        if($taskTime >= $zero){
            return true;
        }
        switch ($zqdType){
            case 0: //全部
                return false;
            case 1: //前1天
                if($taskTime < $zero - 24 * 60 * 60){
                    return true;
                }
                return false;
            case 2: //前2天
                if($taskTime < $zero - 2 * 24 * 60 * 60){
                    return true;
                }
                return false;
            case 3: //前3天
                if($taskTime < $zero - 3 * 24 * 60 * 60){
                    return true;
                }
                return false;
            case 4: //前7天
                if($taskTime < $zero - 7 * 24 * 60 * 60){
                    return true;
                }
                return false;
        }
        return false;
    }


    /**
     * 排除ip重复的用户
     * @param $user
     * @return bool
     */
    private function isIpRepeat($user){
        if (SystemConfig::findValue('dispatch.iprepeatlimit') != 1) {
            return false;
        }
        if(empty(trim($user['ip']))){
            return false;
        }
        $pushTask = PushTask::where('task_type', 1)
            ->whereIn('status', [7, 8])
            ->where('shop_id', $this->tasks['shop_id'])->where('ip', 'like', $user['ip']);
        $value = SystemConfig::findValue('posputplan.ip');
        if ($value) {
            $st = (time() - ($value * 24 * 60 * 60));
            $et = time();
            $pushTask->whereBetween('create_time', [$st, $et]);
            $pushTask = $pushTask->first();
            if($pushTask){
                return true;
            }
        }
        return false;
    }

    /**
     * 判断是否已经超过做单限制
     * @param $pushId
     * @param $platformType
     * @return bool
     */
    private function isTaskNumLimit($pushId)
    {
        $threeDay = SystemConfig::findValue('scrubbuy.treday');
        $configs['scrubbuy.treday'] = $threeDay;
        $sevenDay = SystemConfig::findValue('scrubbuy.sevday');
        $configs['scrubbuy.sevday'] = $sevenDay;
        $month = SystemConfig::findValue('scrubbuy.mouth');
        $configs['scrubbuy.mouth'] = $month;
        foreach ($configs as $key => $value) {
            if ($key == 'scrubbuy.treday') {
                $date = [
                    'start_time' => strtotime(date('Y-m-d 00:00:00', time())),
                    'end_time' => strtotime(date('Y-m-d 23:59:59', time()))
                ];
            }elseif($key == 'scrubbuy.sevday') {
                $date = [
                    'start_time' => strtotime(date('Y-m-d 00:00:00', (time() - 6 * 24 * 60 * 60))),
                    'end_time' => strtotime(date('Y-m-d 23:59:59', time()))
                ];
            }elseif ($key == 'scrubbuy.mouth') {
                $date = [
                    'start_time' => strtotime(date('Y-m-d 00:00:00', (time() - 29 * 24 * 60 * 60))),
                    'end_time' => strtotime(date('Y-m-d 23:59:59', time()))
                ];
            }else{
                break;
            }

            $platformType = [1, 2, 4];
            $ret = PushTask::whereIn('status', [6, 7])->where('task_type', 1)
                ->where('push_id', $pushId)
                ->where('shop_type', $platformType);
            if (isset($date)) {
                $ret->whereBetween('receive_time', [$date['start_time'], $date['end_time']]);
            }
            $ret = $ret->count();
            if ($ret >= $value) {
                return true;
            }
        }
        return false;
    }


    /**
     * 是否强制派单
     * @param false $isZqd
     * @return bool
     */
    private function isForceDispatch()
    {
        // 凌晨强制派单不生效
        $hour = date('H', time());
        if ($hour >= 0 && $hour < 7) {
            return false;
        }
        if (!$this->isZqd) {
            if (in_array($this->tasks['platform_type'], [1, 2, 4])) { // 淘宝
                return SystemConfig::findValue('dispatch.forcedispatch1', 2) == 1;
            }

            if (in_array($this->tasks['platform_type'], [3, 13, 15])) { // 其他
                return SystemConfig::findValue('dispatch.forcedispatch2', 2) == 1;
            }
        }else{
            if (in_array($this->tasks['platform_type'], [1, 2, 4])) { // 淘宝
                return SystemConfig::findValue('dispatch.zqdforcedispatch1', 2) == 1;
            }
            if (in_array($this->tasks['platform_type'], [3, 13, 15])) { // 其他
                return SystemConfig::findValue('dispatch.zqdforcedispatch2', 2) == 1;
            }
        }
        return false;
    }
}
